﻿using System;

using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Silvermoon.Core;
using Silvermoon.Animations;
using Silvermoon.Controls.Classes;

namespace Silvermoon.Controls.Utils
{
    internal static class ContextMenuUtil
    {
        public static Rectangle GetMenuBounds(ContextMenu menu, Control anchor)
        {
            Size size = menu.Size;
            Rectangle bounds = anchor.ToScreenBounds();
            MenuPosition pos = GetOptimalPosition(menu, bounds); 
            Point p = GetPoint(pos, size, bounds);

            Size screenSize = Screen.Current.Size;
            if (p.Y < 0)
            {
                size.Height += p.Y;
                p.Y = 0;
            }
            if (p.X < 0)
            {
                size.Width += p.X;
                p.X = 0;
            }

            Rectangle rect = new Rectangle(p.X, p.Y, size.Width, size.Height);

            if (rect.Top < 0)
            {
                rect.Height += rect.Top;
                rect.Y = 0;
            }
            if (rect.Left < 0)
            {
                rect.Width += rect.Left;
                rect.X = 0;
            }

            if (rect.Bottom > screenSize.Height)
            {
                int d = rect.Bottom - screenSize.Height;
                rect.Y -= d;
                rect.Height = screenSize.Height - rect.Top;
            }
            if (rect.Right > screenSize.Width)
            {
                int d = rect.Right - screenSize.Width;
                rect.X -= d;
                rect.Width = screenSize.Width - rect.Left;
            }

            return rect;
        }

        public static TransitionMode GetTransitionMode(ContextMenu menu, Control anchor)
        {
            MenuPosition pos = GetOptimalPosition(menu, anchor.ToScreenBounds());
            switch (pos)
            {
                case MenuPosition.Top:
                case MenuPosition.TopLeft:
                case MenuPosition.TopRight:
                    return TransitionMode.FadeIn | TransitionMode.SwipeInFromBottom;

                case MenuPosition.Bottom:
                case MenuPosition.BottomLeft:
                case MenuPosition.BottomRight:
                    return TransitionMode.FadeIn | TransitionMode.SwipeInFromTop;

                case MenuPosition.Left:
                case MenuPosition.LeftTop:
                case MenuPosition.LeftBottom:
                    return TransitionMode.FadeIn | TransitionMode.SwipeInFromRight;

                case MenuPosition.Right:
                case MenuPosition.RightTop:
                case MenuPosition.RightBottom:
                    return TransitionMode.FadeIn | TransitionMode.SwipeInFromLeft;

                case MenuPosition.Custom:
                    return TransitionMode.FadeIn;

                default:
                    throw new NotImplementedException(menu.MenuPosition.ToString());
            }
        }

        public static TransitionMode GetReverseTransitionMode(ContextMenu menu, DropDownButton anchor)
        {
            MenuPosition pos = GetOptimalPosition(menu, anchor.ToScreenBounds());
            switch (pos)
            {
                case MenuPosition.Top:
                case MenuPosition.TopLeft:
                case MenuPosition.TopRight:
                    return TransitionMode.FadeOut | TransitionMode.SwipeOutToBottom ;

                case MenuPosition.Bottom:
                case MenuPosition.BottomLeft:
                case MenuPosition.BottomRight:
                    return TransitionMode.FadeOut | TransitionMode.SwipeOutToTop;

                case MenuPosition.Left:
                case MenuPosition.LeftTop:
                case MenuPosition.LeftBottom:
                    return TransitionMode.FadeOut | TransitionMode.SwipeOutToRight;

                case MenuPosition.Right:
                case MenuPosition.RightTop:
                case MenuPosition.RightBottom:
                    return TransitionMode.FadeOut | TransitionMode.SwipeOutToLeft;

                case MenuPosition.Custom:
                    return TransitionMode.FadeOut;

                default:
                    throw new NotImplementedException(menu.MenuPosition.ToString());
            }
        }

        private static MenuPosition GetOptimalPosition(ContextMenu menu, Rectangle bounds)
        {
            MenuPosition mp = menu.MenuPosition;
            Size screenSize = Screen.Current.Size;
            switch (mp)
            {
                case MenuPosition.Top:
                    int w = screenSize.Width / 2;
                    int x = bounds.X+bounds.Width/2;
                    return x < w ? MenuPosition.RightTop : MenuPosition.LeftTop;

                case MenuPosition.Bottom:
                    w = screenSize.Width / 2;
                     x = bounds.X + bounds.Width / 2;
                     return x < w ? MenuPosition.RightBottom : MenuPosition.LeftBottom;

                case MenuPosition.Left:
                     int h = screenSize.Height / 2;
                     int y = bounds.Y - bounds.Height / 2;
                     return y < h ? MenuPosition.BottomLeft : MenuPosition.TopLeft;

                case MenuPosition.Right:
                     h = screenSize.Height / 2;
                     y = bounds.Y - bounds.Height / 2;
                     return y < h ? MenuPosition.BottomRight : MenuPosition.TopRight;

                default: return mp;
            }

        }

        private static Point GetPoint(MenuPosition pos, Size size, Rectangle bounds)
        {
            Point p;

            switch (pos)
            {

                case MenuPosition.TopLeft:
                    p = new Point(bounds.Left, bounds.Top - size.Height);
                    break;

                case MenuPosition.TopRight:
                    p = new Point(bounds.Right - size.Width, bounds.Top - size.Height);
                    break;

                case MenuPosition.BottomLeft:
                    p = new Point(bounds.Left, bounds.Bottom);
                    break;

                case MenuPosition.BottomRight:
                    p = new Point(bounds.Right - size.Width, bounds.Bottom);
                    break;


                case MenuPosition.RightTop:
                    p = new Point(bounds.Right, bounds.Top);
                    break;

                case MenuPosition.RightBottom:
                    p = new Point(bounds.Right, bounds.Top - size.Height);
                    break;

                case MenuPosition.LeftTop:
                    p = new Point(bounds.Left - size.Width, bounds.Top);
                    break;

                case MenuPosition.LeftBottom:
                    p = new Point(bounds.Left - size.Width, bounds.Top - size.Height);
                    break;

                case MenuPosition.Custom:
                    p = Point.Empty;
                    break;

                default:
                    throw new NotImplementedException(pos.ToString());
            }
            return p;
        }


    }
}
